package cn.yeziji.file.listener;

import cn.yeziji.forum.basic.file.WebUploader;
import cn.yeziji.file.dto.FileDTO;
import cn.yeziji.file.handler.channel.CommonHandler;
import cn.yeziji.file.handler.channel.DocsHandler;
import cn.yeziji.file.handler.channel.FileTypeHandler;
import cn.yeziji.file.handler.service.CommonSelected;
import cn.yeziji.file.handler.service.DocsSelected;
import cn.yeziji.file.handler.service.TypeSelected;
import cn.yeziji.file.service.FileService;
import cn.yeziji.forum.common.key.FileCacheKey;
import cn.yeziji.forum.utils.CacheUtils;
import com.github.benmanes.caffeine.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * 文件 redis 监听器
 *
 * @author gzkemays
 * @since 2022/5/18 8:11
 */
@Component
@Slf4j
public class FileRedisListener extends KeyExpirationEventMessageListener {
  @Resource CacheUtils cache;
  @Resource FileService fileService;
  @Resource(name = "fileCache")
  Cache<String, Object> fileCache;

  public FileRedisListener(RedisMessageListenerContainer listenerContainer) {
    super(listenerContainer);
  }

  @PostConstruct
  public void initCaffeineCache() {
    this.cache.newCaffeineCache(fileCache);
  }

  @Override
  public void onMessage(Message message, byte[] pattern) {
    String key = message.toString();
    if (key.contains(FileCacheKey.FILE_UPLOAD_CACHE)) {
      int chunk, chunks;
      String path, filename;
      Map<Object, Object> hashMaps = cache.getHashMaps(key);
      if (!hashMaps.isEmpty()) {
        TreeMap<Object, Object> treeMap =
            new TreeMap<>(
                (o1, o2) -> {
                  int i = Integer.parseInt(String.valueOf(o1));
                  int i2 = Integer.parseInt(String.valueOf(o2));
                  if (i > i2) {
                    return 1;
                  } else if (i < i2) {
                    return -1;
                  }
                  return 0;
                });
        treeMap.putAll(hashMaps);
        Map.Entry<Object, Object> lastEntry = treeMap.lastEntry();
        Object value = lastEntry.getValue();
        if (value instanceof WebUploader.ChuckEntity) {
          WebUploader.ChuckEntity chuckEntity = (WebUploader.ChuckEntity) value;
          // 如果缓存过期的时候，当前缓存对象是完成了上传的，即：chunk == chunks
          path = chuckEntity.getPath();
          filename = chuckEntity.getOriginalFilename();
          chunk = chuckEntity.getChunk();
          chunks = chuckEntity.getChunks();
          // 上传完毕
          if (Objects.equals(chunk, chunks - 1)) {
            if (path.equals(TypeSelected.DOCS_PATH)) {
              FileTypeHandler docsHandler = new DocsHandler(new DocsSelected(filename));
              docsHandler.handler(chuckEntity);
            } else if (path.equals(TypeSelected.COMMON_PATH)) {
              FileTypeHandler commonHandler = new CommonHandler(new CommonSelected(path, chunks));
              commonHandler.handler(chuckEntity);
            }
          } else {
            // 如果未完成上传则删除文件
            fileService.deleteFile(new FileDTO(path, filename));
          }
          cache.getCaffeineCache().invalidate(key);
        }
      }
    }
  }
}
